package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.DmcYingShiCameraMapper;
import com.csun.cmny.provider.device.yingshi.YingShiUtils;
import com.csun.cmny.provider.device.yingshi.entity.YingShiDeviceCameraVo;
import com.csun.cmny.provider.device.yingshi.entity.YingShiDeviceInfoVo;
import com.csun.cmny.provider.device.yingshi.entity.YingShiDeviceVo;
import com.csun.cmny.provider.exceptions.DmcBizException;
import com.csun.cmny.provider.model.domain.*;
import com.csun.cmny.provider.model.dto.propertyManagement.MerchantSaveDeviceDto;
import com.csun.cmny.provider.model.dto.propertyManagement.SelectDeviceDataDto;
import com.csun.cmny.provider.model.dto.yingshi.YingShiCameraDto;
import com.csun.cmny.provider.model.dto.yingshi.YingShiCameraQueryDto;
import com.csun.cmny.provider.model.enums.device.DeviceStatusEnum;
import com.csun.cmny.provider.model.enums.device.DmcDeviceTypeEnum;
import com.csun.cmny.provider.model.vo.GroupVo;
import com.csun.cmny.provider.model.vo.propertyManagement.PropertyDataVo;
import com.csun.cmny.provider.model.vo.yingshi.GroupCameraTreeVo;
import com.csun.cmny.provider.model.vo.yingshi.YingShiCameraVo;
import com.csun.cmny.provider.model.vo.yingshi.YsCameraChannelVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.provider.utils.YsGroupTreeUtils;
import com.csun.cmny.util.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2021/8/27 16:42
 * @Description: 萤石摄像头接口实现
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DmcYingShiCameraServiceImpl extends BaseService<DmcYingShiCamera>
        implements DmcYingShiCameraService {

    @Resource
    private DmcYingShiCameraMapper dmcYingShiCameraMapper;
    @Resource
    private DmcYingShiChannelService dmcYingShiChannelService;
    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private DmcDeviceService dmcDeviceService;
    @Resource
    private YingShiUtils yingShiUtils;
    @Resource
    private DmcYingShiConfigService dmcYingShiConfigService;
    @Resource
    private DmcPropertyManagementService propertyManagementService;

    /**
     * 查询萤石摄像头列表 - 分页
     *
     * @param yingShiCameraQueryDto the ying shi camera query dto
     *
     * @return  the ying shi camera vo list.
     */
    @Override
    public List<YingShiCameraVo> queryListWithPage(YingShiCameraQueryDto yingShiCameraQueryDto) {

        PageHelper.startPage(yingShiCameraQueryDto.getPageNum(), yingShiCameraQueryDto.getPageSize());

        List<YingShiCameraVo> yingShiCameraVoList = dmcYingShiCameraMapper.queryListWithPage(yingShiCameraQueryDto);

        // 获取设备状态
        if (PublicUtil.isNotEmpty(yingShiCameraVoList)) {
            // 获取token
            DmcYingShiConfig dmcYingShiConfig = dmcYingShiConfigService.selectByKey(yingShiCameraQueryDto.getGroupId());
            if (PublicUtil.isEmpty(dmcYingShiConfig)) {
                throw new DmcBizException(ErrorCodeEnum.DMC100622009);
            }
            List<YingShiDeviceVo> yingShiDeviceVoList = yingShiUtils
                    .getDeviceList(dmcYingShiConfig.getAccessToken());
            if (PublicUtil.isNotEmpty(yingShiDeviceVoList)) {
                Map<String, YingShiDeviceVo> yingShiDeviceVoMap =
                        yingShiDeviceVoList.stream().collect(Collectors.toMap(YingShiDeviceVo::getDeviceSerial, a -> a, (k1, k2) -> k1));

                for (YingShiCameraVo yscv : yingShiCameraVoList) {
                    yscv.setStatus(DeviceStatusEnum.OFFLINE.getKey());
                    YingShiDeviceVo vo = yingShiDeviceVoMap.get(yscv.getDeviceNo());
                    if (PublicUtil.isNotEmpty(vo) && vo.getStatus().equals(1)) {    // 在线
                        yscv.setStatus(DeviceStatusEnum.ONLINE.getKey());
                    }
                }
            }
        }

        return yingShiCameraVoList;
    }

    /**
     * 添加萤石摄像头信息
     *
     * @param yingShiCameraDto  the ying shi camera dto
     * @param loginAuthDto  the login auth dto
     *
     * @return  the int.
     */
    @Override
    public Integer save(YingShiCameraDto yingShiCameraDto, LoginAuthDto loginAuthDto) {

        // 获取token
        DmcYingShiConfig dmcYingShiConfig = dmcYingShiConfigService.selectByKey(loginAuthDto.getGroupId());
        if (PublicUtil.isEmpty(dmcYingShiConfig)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622009);
        }

        // 校验是否有效
        YingShiDeviceInfoVo yingShiDeviceInfoVo = yingShiUtils
                .getDeviceInfo(dmcYingShiConfig.getAccessToken(), yingShiCameraDto.getDeviceNo());
        // 20002 设备不存在
        // 20014 deviceSerial不合法

//        DmcDevice dmcDevice = new DmcDevice();
//        dmcDevice.setDeviceType(DmcDeviceTypeEnum.YS_CAMERA.getIndex());
//        dmcDevice.setDeviceName(yingShiCameraDto.getDeviceName());
//        dmcDevice.setDeviceNo(yingShiCameraDto.getDeviceNo());
//        dmcDevice.setRemark(yingShiCameraDto.getRemark());
//        Integer result = dmcDeviceService.addDevice(dmcDevice, loginAuthDto);

        DmcDevice dmcDevice = dmcDeviceService.queryDeviceByNumber(yingShiCameraDto.getDeviceNo());
        Preconditions.checkArgument(PublicUtil.isNotEmpty(dmcDevice),
                cmnyMessageSource.getMessage("excel.deviceNo.sql.null", null));


        // 校验此设备是否被此机构购买
        DmcPropertyManagement dmcPropertyManagement = propertyManagementService.selectByKey(dmcDevice.getId());

        Preconditions.checkArgument(dmcPropertyManagement.getBuyGroupId().equals(loginAuthDto.getGroupId()),
                cmnyMessageSource.getMessage("managent.device.error", null));

        Preconditions.checkArgument(dmcDevice.getGroupId().equals(0l),
                cmnyMessageSource.getMessage("device.bing.group.error", null));

        // 绑定商家与设备
        MerchantSaveDeviceDto merchantSaveDeviceDto = new MerchantSaveDeviceDto();
        merchantSaveDeviceDto.setDeviceNo(yingShiCameraDto.getDeviceNo());
        merchantSaveDeviceDto.setDeviceName(yingShiCameraDto.getDeviceName());
        merchantSaveDeviceDto.setRemark(yingShiCameraDto.getRemark());
        int result = dmcDeviceService.bindOnedeviceGroup(merchantSaveDeviceDto, loginAuthDto.getGroupId());

        if (result > 0) {
            DmcYingShiCamera dmcYingShiCamera = new DmcYingShiCamera();
            dmcYingShiCamera.setDeviceId(dmcDevice.getId());
            dmcYingShiCamera.setCode(yingShiCameraDto.getCode());
            dmcYingShiCamera.setCreator(loginAuthDto.getUserName());
            dmcYingShiCamera.setCreatorId(loginAuthDto.getUserId());

            return dmcYingShiCameraMapper.insertSelective(dmcYingShiCamera);
        }

        return result;
    }

    /**
     * 修改萤石摄像头信息
     *
     * @param yingShiCameraDto  the ying shi camera dto
     * @param loginAuthDto  the login auth dto
     *
     * @return  the int.
     */
    @Override
    public Integer edit(YingShiCameraDto yingShiCameraDto, LoginAuthDto loginAuthDto) {

        Preconditions.checkArgument(PublicUtil.isNotEmpty(yingShiCameraDto.getId()),
                cmnyMessageSource.getMessage("ying.shi.camera.id.null", null));

        // 校验萤石摄像头是否存在
        DmcYingShiCamera dmcYingShiCamera = dmcYingShiCameraMapper.selectByPrimaryKey(yingShiCameraDto.getId());
        if (PublicUtil.isEmpty(dmcYingShiCamera)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622007);
        }

        DmcDevice dmcDevice = new DmcDevice();
        dmcDevice.setDeviceType(DmcDeviceTypeEnum.YS_CAMERA.getIndex());
        dmcDevice.setId(yingShiCameraDto.getId());
        dmcDevice.setDeviceName(yingShiCameraDto.getDeviceName());
        dmcDevice.setDeviceNo(yingShiCameraDto.getDeviceNo());
        dmcDevice.setRemark(yingShiCameraDto.getRemark());
        Integer result = dmcDeviceService.editDevice(dmcDevice, loginAuthDto);
        if (result > 0) {
            if (PublicUtil.isNotEmpty(yingShiCameraDto.getCode())) {
                dmcYingShiCamera = new DmcYingShiCamera();
                dmcYingShiCamera.setDeviceId(dmcDevice.getId());
                dmcYingShiCamera.setCode(yingShiCameraDto.getCode());

                return dmcYingShiCameraMapper.updateByPrimaryKeySelective(dmcYingShiCamera);
            }
        }

        return result;
    }

    /**
     * 根据id删除萤石摄像头信息
     *
     * @param id    the ying shi camera id
     *
     * @return  the int.
     */
    @Override
    public Integer deleteById(Long id) {

        DmcYingShiChannel dmcYingShiChannel = new DmcYingShiChannel();
        dmcYingShiChannel.setDeviceId(id);
        int count = dmcYingShiChannelService.selectCount(dmcYingShiChannel);
        if (count > 0) {
            throw new DmcBizException(ErrorCodeEnum.DMC100622008);
        }

        // dmcDeviceService.deleteByKey(id);
        dmcDeviceService.deleteuntie(Lists.newArrayList(id));

        return dmcYingShiCameraMapper.deleteByPrimaryKey(id);
    }

    /**
     * 查询萤石摄像头的数据
     *
     * @param selectDeviceDataDto   the select device data dto
     *
     * @return  the property data vo
     */
    @Override
    public List<PropertyDataVo> selectDeviceData(SelectDeviceDataDto selectDeviceDataDto) {

        PageHelper.startPage(selectDeviceDataDto.getPageNum(), selectDeviceDataDto.getPageSize());

        List<PropertyDataVo> propertyDataVoList = dmcYingShiCameraMapper.selectDeviceData(selectDeviceDataDto);

        // TODO 查询摄像头状态

        return propertyDataVoList;
    }

    /**
     * 获取机构摄像头列表
     *
     * @param groupVoList   the group vo list
     *
     * @return  the group camera tree vo list.
     */
    @Override
    public List<GroupCameraTreeVo> queryGroupCameraList(List<GroupVo> groupVoList, Long groupId) {

        List<GroupCameraTreeVo> groupCameraTreeVoList = Lists.newArrayList();
        for (GroupVo gv : groupVoList) {
            GroupCameraTreeVo gctv = new GroupCameraTreeVo();
            gctv.setGroupId(gv.getId());
            gctv.setGroupName(gv.getGroupName());
            gctv.setPid(gv.getPid());
            gctv.setCameraVoList(dmcYingShiCameraMapper.getCameraChannelList(gctv.getGroupId()));

            groupCameraTreeVoList.add(gctv);
        }

        return YsGroupTreeUtils.getChildMenuVos(groupCameraTreeVoList, groupId);
    }

    /**
     * 查询摄像头通道列表
     *
     * @param yingShiCameraQueryDto the ying shi camera query dto
     *
     * @return  the ying shi camera channel vo list.
     */
    @Override
    public List<YsCameraChannelVo> getChannelList(YingShiCameraQueryDto yingShiCameraQueryDto) {

        PageHelper.startPage(yingShiCameraQueryDto.getPageNum(), yingShiCameraQueryDto.getPageSize());

        List<YsCameraChannelVo> ysCameraChannelVoList = dmcYingShiCameraMapper.getChannelList(yingShiCameraQueryDto);
        if (PublicUtil.isNotEmpty(ysCameraChannelVoList)) {

            Map<Long, Map<Integer, YingShiDeviceCameraVo>> cameraMap = getChannelStatus(ysCameraChannelVoList);

            for (YsCameraChannelVo vo : ysCameraChannelVoList) {
                vo.setStatus(DeviceStatusEnum.OFFLINE.getKey());
                Map<Integer, YingShiDeviceCameraVo> cameraVo = cameraMap.get(vo.getDeviceId());
                if (PublicUtil.isNotEmpty(cameraVo)) {
                    YingShiDeviceCameraVo channelVo = cameraVo.get(vo.getChannelNo());
                    if (PublicUtil.isNotEmpty(channelVo) && channelVo.getStatus().equals(1)) {    // 在线
                        vo.setStatus(DeviceStatusEnum.ONLINE.getKey());
                    }
                }
            }
        }

        return ysCameraChannelVoList;
    }

    /**
     * 获取萤石摄像头通道状态
     *
     * @param ysCameraChannelVoList the ying shi camera channel vo list
     *
     * @return  the ying shi device camera vo map.
     */
    @Override
    public Map<Long, Map<Integer, YingShiDeviceCameraVo>> getChannelStatus(List<YsCameraChannelVo> ysCameraChannelVoList) {

        Map<Long, Map<Integer, YingShiDeviceCameraVo>> cameraVoMap = Maps.newHashMap();

        Map<Long, DmcYingShiConfig> configMap = Maps.newHashMap();

        for (YsCameraChannelVo vo : ysCameraChannelVoList) {

            DmcYingShiConfig config = configMap.get(vo.getGroupId());
            if (PublicUtil.isEmpty(config)) {
                config = dmcYingShiConfigService.selectByKey(vo.getGroupId());
                if (PublicUtil.isNotEmpty(config)) {
                    configMap.put(vo.getGroupId(), config);
                }
            }

            if (PublicUtil.isEmpty(config)) {
                continue;
            }

            Map<Integer, YingShiDeviceCameraVo> channelVo = cameraVoMap.get(vo.getDeviceId());
            if (PublicUtil.isEmpty(channelVo)) {

                List<YingShiDeviceCameraVo> yingShiDeviceCameraVoList = yingShiUtils
                        .getDeviceCameraList(config.getAccessToken(), vo.getDeviceNo());

                if (PublicUtil.isNotEmpty(yingShiDeviceCameraVoList)) {
                    Map<Integer, YingShiDeviceCameraVo> yingShiDeviceCameraVoMap =
                            yingShiDeviceCameraVoList.stream().collect(Collectors.toMap(YingShiDeviceCameraVo::getChannelNo, a -> a, (k1, k2) -> k1));

                    cameraVoMap.put(vo.getDeviceId(), yingShiDeviceCameraVoMap);
                }
            }
        }

        return cameraVoMap;
    }
}
